package com.sq.util;

import com.sq.util.exception.CommonException;
import com.sq.util.exception.VisualException;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
public class StringUtil {
    private static final String RANDOM_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 获得一个随机的字符串
     *
     * @param len
     * @return
     */
    public static String getRandomString(int len) {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        char[] buf = new char[len];
        for (int i = 0; i < len; i++) {
            buf[i] = RANDOM_CHARS.charAt(random.nextInt(RANDOM_CHARS.length()));
        }
        return new String(buf);
    }

    /**
     * 首字母大写
     *
     * @param str
     * @return
     */
    public static String upCaseFirst(String str) {
        char[] arr = str.toCharArray();
        arr[0] = Character.toUpperCase(arr[0]);
        return new String(arr);
    }

    public static String trim(String str) {
        if (str == null) {
            return "";
        }
        return str.trim();
    }

    /**
     * 检查空字符串，或者" "字符串
     *
     * @param str
     * @return
     */
    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNotBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return false;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 把字符串str里面#{key}，替换为param的value
     * 如 ： str是aa#{bb}cc#{dd}, param是{"bb":"11"}，结果为aa11cc#{dd}
     */
    public static String replaceObjectParam(String str, Map<String, Object> param) {
        return replaceObjectParam(str, param, false);
    }


    /**
     * 把字符串str里面#{key}，替换为param的value
     * 如 ： str是aa#{bb}cc#{dd}, param是{"bb":"11"}，结果为aa11cc#{dd}
     *
     * @param check 为true时，如果替换时发现param不存在，会报错
     */
    public static String replaceObjectParam(String str, Map<String, Object> param, boolean check) {
        char[] formatArr = str.toCharArray();
        char[] p1Arr = "#{".toCharArray();
        char[] p2Arr = "}".toCharArray();
        boolean isFoundHead = false;
        StringBuilder result = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        for (int i = 0; i < formatArr.length; i++) {
            char c = formatArr[i];
            if (!isFoundHead && c == p1Arr[0] && isMatch(formatArr, i, p1Arr)) {// 找到开头
                i += p1Arr.length - 1;
                isFoundHead = true;
                continue;
            }
            if (isFoundHead) {
                if (c == p2Arr[0] && isMatch(formatArr, i, p2Arr)) {// 找到结尾
                    String key = temp.toString();
                    Object object = getObjectWithKey(key, param);
                    if (object != null) {
                        result.append(object);
                    } else {
                        if (check) {
                            throw new CommonException("param不存在参数:{}", key);
                        } else {
                            result.append(p1Arr).append(temp).append(p2Arr);
                        }
                    }
                    i += p2Arr.length - 1;
                    isFoundHead = false;
                    temp = new StringBuilder();
                } else {
                    temp.append(c);
                }
            } else {
                result.append(c);
            }
        }
        return result.toString();
    }

    private static Object getObjectWithKey(String key, Map<String, Object> param) {
        String[] arr = key.split("\\.");
        int length = arr.length;
        if (length == 1) {
            return param.get(key);
        }
        Object obj = param.get(arr[0]);
        for (int i = 1; i < length; i++) {
            Object o = getValueFromObj(arr[i], obj);
            if (i == length - 1) {
                return o;
            } else {
                obj = o;
            }
        }
        return null;
    }

    private static Object getValueFromObj(String key, Object object) {
        if (object instanceof Map) {
            return ((Map) object).get(key);
        }
        try {
            return BeanUtil.getValue(object, key);
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
            return null;
        }

    }

    /**
     * 把字符串str里面#{key}，替换为param的value
     * 如 ： str是aa#{bb}cc#{dd}, param是{"bb":"11"}，结果为aa11cc#{dd}
     */
    public static String replaceParam(String str, Map<String, String> param) {
        return replaceParam(str, param, false);
    }

    /**
     * 把字符串str里面#{key}，替换为param的value
     * 如 ： str是aa#{bb}cc#{dd}, param是{"bb":"11"}，结果为aa11cc#{dd}
     *
     * @param check 为true时，如果替换时发现param不存在，会报错
     */
    public static String replaceParam(String str, Map<String, String> param, boolean check) {
        char[] formatArr = str.toCharArray();
        char[] p1Arr = "#{".toCharArray();
        char[] p2Arr = "}".toCharArray();
        boolean isFoundHead = false;
        StringBuilder result = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        for (int i = 0; i < formatArr.length; i++) {
            char c = formatArr[i];
            if (!isFoundHead && c == p1Arr[0] && isMatch(formatArr, i, p1Arr)) {// 找到开头
                i += p1Arr.length - 1;
                isFoundHead = true;
                continue;
            }
            if (isFoundHead) {
                if (c == p2Arr[0] && isMatch(formatArr, i, p2Arr)) {// 找到结尾
                    String key = temp.toString();
                    String value = param.get(key);
                    if (value != null) {
                        result.append(value);
                    } else {
                        if (check) {
                            throw new CommonException("param不存在参数:{}", key);
                        } else {
                            result.append(p1Arr).append(temp).append(p2Arr);
                        }
                    }
                    i += p2Arr.length - 1;
                    isFoundHead = false;
                    temp = new StringBuilder();
                } else {
                    temp.append(c);
                }
            } else {
                result.append(c);
            }
        }
        return result.toString();
    }

    /**
     * 把字符串str里面全部的p1.*p2，替换为r1.*r2
     */
    public static String replacePair(String str, String p1, String p2, String r1, String r2) {
        char[] strArr = str.toCharArray();
        char[] p1Arr = p1.toCharArray();
        char[] p2Arr = p2.toCharArray();
        boolean isFoundHead = false;
        StringBuilder result = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        for (int i = 0; i < strArr.length; i++) {
            char c = strArr[i];
            if (!isFoundHead && c == p1Arr[0] && isMatch(strArr, i, p1Arr)) {// 找到开头
                i += p1Arr.length - 1;
                isFoundHead = true;
                continue;
            }
            if (isFoundHead) {
                if (c == p2Arr[0] && isMatch(strArr, i, p2Arr)) {// 找到结尾
                    result.append(r1).append(temp).append(r2);
                    i += p2Arr.length - 1;
                    isFoundHead = false;
                    temp = new StringBuilder();
                } else {
                    temp.append(c);
                }
            } else {
                result.append(c);
            }
        }
        if (temp.length() != 0) {
            result.append(p1Arr).append(temp);
        }
        return result.toString();
    }

    /**
     * 把字符串str里面全部的startStr到endStr的source替换为target
     */
    public static String replaceBetween(String str, String startStr, String endStr, String source, String target) {
        char[] strArr = str.toCharArray();
        char[] p1Arr = startStr.toCharArray();
        char[] p2Arr = endStr.toCharArray();
        boolean isFoundHead = false;
        StringBuilder result = new StringBuilder();
        StringBuilder temp = new StringBuilder();
        for (int i = 0; i < strArr.length; i++) {
            char c = strArr[i];
            if (!isFoundHead && c == p1Arr[0] && isMatch(strArr, i, p1Arr)) {// 找到开头
                i += p1Arr.length - 1;
                isFoundHead = true;
                continue;
            }
            if (isFoundHead) {
                if (c == p2Arr[0] && isMatch(strArr, i, p2Arr)) {// 找到结尾
                    result.append(startStr);
                    result.append(temp.toString().replace(source, target));
                    result.append(endStr);
                    i += p2Arr.length - 1;
                    isFoundHead = false;
                    temp = new StringBuilder();
                } else {
                    temp.append(c);
                }
            } else {
                result.append(c);
            }
        }
        if (temp.length() != 0) {
            result.append(p1Arr).append(temp);
        }
        return result.toString();
    }

    /**
     * 从s1中截取s2和s3中间的字符串,找不到返回null
     */
    public static String getBetweenString(String str, String s1, String s2) {
        char[] strArr = str.toCharArray();
        char[] s1Arr = s1.toCharArray();
        char[] s2Arr = s2.toCharArray();
        boolean isFoundHead = false;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < strArr.length; i++) {
            if (!isFoundHead && strArr[i] == s1Arr[0] && isMatch(strArr, i, s1Arr)) {// 找到开头
                i += s1Arr.length;
                isFoundHead = true;
            }
            if (isFoundHead) {
                if (strArr[i] == s2Arr[0] && isMatch(strArr, i, s2Arr)) {// 找到结尾
                    return sb.toString().trim();
                } else {
                    sb.append(strArr[i]);
                }
            }
        }
        return null;
    }

    // 从arr1的start匹配arr2
    public static boolean isMatch(char[] arr1, int start, char[] arr2) {
        int l2 = arr2.length;
        int l1 = arr1.length;
        if (l2 + start > l1) {
            return false;
        }
        for (int j = 0; j < l2; j++) {
            if (arr1[start + j] != arr2[j]) {
                return false;
            }
        }
        return true;
    }

    public static Object convert(Class<?> cls, String s) {
        if (s == null || cls == null) {
            return null;
        }
        if (cls.equals(String.class)) {
            return s;
        }
        if (cls.equals(boolean.class) || cls.equals(Boolean.class)) {
            if (isBlank(s)) {
                return false;
            }
            s = s.trim();
            if ("1".equals(s) || "true".equalsIgnoreCase(s)) {
                return true;
            }
            return false;
        }
        if (isBlank(s)) {
            return null;
        }
        if (ClassUtil.isInt(cls)) {
            return Integer.valueOf(s);
        } else if (ClassUtil.isLong(cls)) {
            return Long.valueOf(s);
        } else if (ClassUtil.isDouble(cls)) {
            return Double.valueOf(s);
        } else if (cls.equals(BigDecimal.class)) {
            return new BigDecimal(s);
        } else if (cls.equals(short.class) || cls.equals(Short.class)) {
            return Short.valueOf(s);
        } else if (cls.equals(Date.class)) {
            if (s.length() == DateFormats.DATE_FORMAT.length()) {
                return DateUtil.strToDate(s);
            } else if (s.length() == DateFormats.DATE_TIME_FORMAT.length()) {
                return DateUtil.strToTime(s);
            } else {
                throw new VisualException("格式不对,需要为:[{}]或者[{}]", DateFormats.DATE_FORMAT, DateFormats.DATE_TIME_FORMAT);
            }
        } else if (cls.equals(LocalDate.class)) {
            VisualException.isTrue(s.length() == DateFormats.DATE_FORMAT.length(), "日期格式不对,需要为:[{}]",
                    DateFormats.DATE_FORMAT);
            return DateUtil.toLocalDate(s);
        } else if (cls.equals(LocalDateTime.class)) {
            VisualException.isTrue(s.length() == DateFormats.DATE_TIME_FORMAT.length(), "日期时间格式不对,需要为:[{}]",
                    DateFormats.DATE_TIME_FORMAT);
            return DateUtil.toLocalDateTime(s);
        }
        throw new CommonException("不支持类型" + cls.getName());
    }

    public static String getFileType(String fileName) {
        if (fileName == null) {
            return null;
        }
        int index = fileName.lastIndexOf(".");
        if (index < 0) {
            return null;
        }
        return fileName.substring(index);
    }

    public static String numberToString(int num, int length) {
        String numStr = Integer.toString(num);
        int numLength = numStr.length();
        VisualException.isTrue(length >= numLength, num + "的位数超过" + length);
        int n = length - numLength;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append("0");
        }
        sb.append(numStr);
        return sb.toString();
    }

    public static List<String> strToList(String str, String regex) {
        String[] arr = StringUtil.trim(str).split(regex);
        List<String> result = new ArrayList<>(arr.length);
        for (String s : arr) {
            if (StringUtil.isBlank(s)) {
                continue;
            }
            result.add(StringUtil.trim(s));
        }
        return result;
    }

    /**
     * 字符串加1，如：传入002返回003
     */
    public static String strAddOne(String str) {
        int length = str.length();
        VisualException.isTrue(length < 10, "字符串长度不能超过9位");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append("0");
        }
        int sum = Integer.parseInt(str) + 1;
        String sumStr = Integer.toString(sum);
        VisualException.isTrue(length >= sumStr.length(), "字符串溢出");
        sb.append(sumStr);
        String result = sb.substring(sb.length() - length);
        return result;
    }

    /**
     * @param format 把{}替换为args的参数
     * @param args
     * @return
     */
    public static String format(String format, Object... args) {
        if (format == null) {
            return "";
        }
        if (args == null || args.length == 0 || format.length() < 2) {
            return format;
        }
        char[] arr = format.toCharArray();
        StringBuilder sb = new StringBuilder(arr.length);
        int argIndex = 0, argLength = args.length;
        int i = 0, length = arr.length - 1;
        for (; i < length; i++) {
            char c = arr[i];
            if (c == '{' && argIndex < argLength && arr[i + 1] == '}') {
                i++;
                sb.append(args[argIndex++]);
                continue;
            }
            sb.append(c);
        }
        char c = arr[length];
        if (c != '}') {
            sb.append(c);
        } else {
            length = sb.length();
            if (length > 0 && sb.charAt(length - 1) == '{') {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static boolean startWith(String sourceString, String startString) {
        CommonException.assertNotNull(sourceString, "sourceString不能为空");
        CommonException.assertNotNull(startString, "sourceString不能为空");
        int length = startString.length();
        if (length == 0) {
            return true;
        }
        if (sourceString.length() < length) {
            return false;
        }
        char[] sourceArr = sourceString.toCharArray();
        char[] startArr = startString.toCharArray();
        for (int i = 0, len = startArr.length; i < len; i++) {
            if (sourceArr[i] != startArr[i]) {
                return false;
            }
        }
        return true;
    }

    public static boolean endWith(String sourceString, String endString) {
        CommonException.assertNotNull(sourceString, "sourceString不能为空");
        CommonException.assertNotNull(endString, "endString不能为空");
        int length = endString.length();
        if (length == 0) {
            return true;
        }
        if (sourceString.length() < length) {
            return false;
        }
        char[] sourceArr = sourceString.toCharArray();
        char[] endArr = endString.toCharArray();
        int sourceIndex = sourceArr.length - 1;
        int endIndex = endArr.length - 1;
        while (endIndex >= 0) {
            if (sourceArr[sourceIndex] != endArr[endIndex]) {
                return false;
            }
            endIndex--;
            sourceIndex--;
        }
        return true;
    }
}
